package com.openlogic.common.plugins.spi.plugin;

import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.ServiceLoader;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * @ClassName: PrioritySPIFactory
 * @Description: 优先级插件加载工厂
 * @author weiyongpeng
 * @date 2025年1月23日 下午8:51:10
 * @param <T>
 */
public class PrioritySPIFactory<T extends PrioritySPI> {

	private static final Logger log = LoggerFactory.getLogger(PrioritySPIFactory.class);

	/**
	 * 插件集MAP
	 */
	private final Map<String, T> map = new HashMap<>();

	public PrioritySPIFactory(Class<T> spiClass) {
		for (T t : ServiceLoader.load(spiClass)) {
			if (map.containsKey(t.getIdentify().getName())) {
				resolveConflict(t);
			} else {
				map.put(t.getIdentify().getName(), t);
			}
		}
	}

	public Map<String, T> getSPIMap() {
		return Collections.unmodifiableMap(map);
	}

	/**
	 * 描述：冲突解决机制，优先级高的覆盖优先级低的(同名),否则抛出异常
	 * 
	 * @Title: resolveConflict
	 * @param newSPI
	 * @author weiyongpeng
	 * @date 2024年11月16日 上午8:22:35
	 */
	private void resolveConflict(T newSPI) {
		SPIIdentify identify = newSPI.getIdentify();
		T oldSPI = map.get(identify.getName());

		if (newSPI.compareTo(oldSPI.getIdentify().getPriority()) == 0) {
			throw new IllegalArgumentException(
					String.format("These two spi plugins has conflict identify name with the same priority: %s, %s",
							oldSPI.getIdentify(), newSPI.getIdentify()));
		} else if (newSPI.compareTo(oldSPI.getIdentify().getPriority()) > 0) {
			log.info("The {} plugin has high priority, will override {}", newSPI.getIdentify(), oldSPI);
			map.put(identify.getName(), newSPI);
		} else {
			log.info("The low plugin {} will be skipped", newSPI);
		}
	}
}
